package com.quad.innovators.salesease.aspect;

import cn.hutool.core.util.StrUtil;
import com.quad.innovators.salesease.annotation.RepeatSubmit;
import com.quad.innovators.salesease.constants.CacheConstants;
import com.quad.innovators.salesease.constants.SecurityConstants;
import com.quad.innovators.salesease.context.UserContext;
import com.quad.innovators.salesease.enums.ResultCode;
import com.quad.innovators.salesease.exception.BusinessException;
import com.quad.innovators.salesease.lock.RepeatSubmitLock;
import com.quad.innovators.salesease.model.dto.SysUserAuthInfo;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Objects;
import java.util.Optional;

/**
 * 处理重复提交的切面
 *
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class RepeatSubmitAspect {

    private final RepeatSubmitLock repeatSubmitLock;


    /**
     * 防重复提交切点
     */
    @Pointcut("@annotation(repeatSubmit)")
    public void preventDuplicateSubmitPointCut(RepeatSubmit repeatSubmit) {
        log.info("定义防重复提交切点");
    }

    @Around("preventDuplicateSubmitPointCut(repeatSubmit)")
    public Object doAround(ProceedingJoinPoint pjp, RepeatSubmit repeatSubmit) throws Throwable {
        Optional<String> resubmitLockKeyOptional = generateResubmitLockKey();
        if (resubmitLockKeyOptional.isPresent()) {
            String resubmitLockKey = resubmitLockKeyOptional.get();
            int expire = repeatSubmit.expire(); // 防重提交锁过期时间
            boolean lockResult = repeatSubmitLock.tryLock(resubmitLockKey, expire); // 获取锁失败，直接返回 false
            if (!lockResult) {
                throw  BusinessException.resultCode(ResultCode.REPEAT_SUBMIT_ERROR); // 抛出重复提交提示信息
            }
        }
        return pjp.proceed();
    }


    /**
     * 获取重复提交锁的 key
     */
    private Optional<String> generateResubmitLockKey() {
        String resubmitLockKey = null;
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StrUtil.isNotBlank(token) && token.startsWith(SecurityConstants.TOKEN_PREFIX)) {
            SysUserAuthInfo currentUser = UserContext.getCurrentUser();
            resubmitLockKey = CacheConstants.RESUBMIT_LOCK_PREFIX + currentUser.getUserId() + ":" + request.getMethod() + "-" + request.getRequestURI();
            return Optional.of(resubmitLockKey);
        }
        return Optional.empty();
    }

}
